#################################################################################################
# Group Casting Policy
#
# Used to determine if a selected unit or group can "cast" a spell. In other words, will test if
# the action button should show up in the action list. Note that the bVisible variables work
# as they do in all other functions.
#################################################################################################

import CvUtil
from CvPythonExtensions import *
from GerikSpells import GerikSpellBase

# globals
gc = CyGlobalContext()

class GSBase:
    def __init__(self):
        pass
    
    def canUnitCast(self, pCastingUnit, pCastingPlot, bVisible):
        """
        Arguments:
        pCastingUnit: The unit that will be casting the spell.
        pCastingPlot: The plot the unit will be casting the spell on.
        bVisible: True if we're just checking if the button should be visible
                  False if we're checking if the button should be selectable.

        Returns:
        boolean value, depending on if the unit can cast the spell.

        Used to determine if a specific unit can cast a spell (and thus allowing
        the action button to be placed into their list of action buttons when selected).
        """
        raise NotImplementedError

    def canGroupCast(self, pCastingGroup, pCastingPlot, bVisible):
        """
        Arguments:
        pCastingGroup: The CySelectionGroup we are checking if the spell action button should be shown.
        pCastingPlot: The CyPlot object that the CySelectionGroup is trying to cast the spell from.
        bVisible: True if we're just checking if the button should be visible.
                  False if we're checking if the button should be selectable.

        Returns:
        boolean value, depending on if the group can cast the spell.


        Used to determine if the action button for the spell should be placed in the group's list of
        actions available, and if the group can cast that spell. Note that a unit may be able to
        cast a spell but if in a group with units that can't, the button may or may not appear.
        This function determines that.

        This is called from the SDK, so be sure use a policy or override this function yourself.
        """
        raise NotImplementedError


##########################################
#
# Group Policies
#
##########################################

# GSAll
# Whenever a check for a group is made, the function returns true only if all the units in the group
# return true in their canUnitCast function.
class GSAll(GSBase):
    def __init__(self):
        GSBase.__init__(self)

    def canGroupCast(self, pCastingGroup, pCastingPlot, bVisible):
        for pUnit in pCastingGroup.getUnits():
            if not self.canUnitCast(pUnit, pCastingPlot, bVisible):
                return False

        return True

# GSAny
# Whenever a check for a group is made, the function returns true if any of the units in the group
# return true in their canUnitCast function.
class GSAny(GSBase):
    def __init__(self):
        GSBase.__init__(self)

    def canGroupCast(self, pCastingGroup, pCastingPlot, bVisible):
        for pUnit in pCastingGroup.getUnits():
            if self.canUnitCast(pUnit, pCastingPlot, bVisible):
                return True

        return False

# GSQuota
# Whenever a check for a group is made, the function returns true if a certain number of units in the group
# return true in their canUnitCast function. Set the number by using the setGroupPolicyQuota function
# in the constructor. Ex:
#
#class TestSpell(GSQuota):
#    def __init__(self):
#        GSQuota.__init__(self)
#        self.setGroupPoilcyQuota(3)
#

class GSQuota(GSBase):
    def __init__(self):
        GSBase.__init__(self)
        self.m_iQuota = 1

    def getGroupPolicyQuota(self):
        return self.m_iQuota

    def setGroupPolicyQuota(self, iQuota):
        self.m_iQuota = iQuota

    def canGroupCast(self, pCastingGroup, pCastingPlot, bVisible):
        iNumPassed = 0
        for pUnit in pCastingGroup.getUnits():
            if self.canUnitCast(pUnit, pCastingPlot, bVisible):
                iNumPassed += 1
                if iNumPassed >= self.m_iQuota:
                    return True

        return False

